/****************************************************************************
 *
 * This file is part of the CodeMax editor support code.
 *
 * Primary author: Christopher J. Cason.
 *
 * from Persistence of Vision(tm) Ray Tracer version 3.6.
 * Copyright 1991-2003 Persistence of Vision Team
 * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
 *---------------------------------------------------------------------------
 * NOTICE: This source code file is provided so that users may experiment
 * with enhancements to POV-Ray and to port the software to platforms other
 * than those supported by the POV-Ray developers. There are strict rules
 * regarding how you are permitted to use this file. These rules are contained
 * in the distribution and derivative versions licenses which should have been
 * provided with this file.
 *
 * These licences may be found online, linked from the end-user license
 * agreement that is located at http://www.povray.org/povlegal.html
 *---------------------------------------------------------------------------
 * This program is based on the popular DKB raytracer version 2.12.
 * DKBTrace was originally written by David K. Buck.
 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
 *---------------------------------------------------------------------------
 * Thanks to WinMain Software (http://www.winmain.com/) for providing the (at
 * the time commercial) CodeMax edit control which the POVWIN editor is based.
 *---------------------------------------------------------------------------
 * $File: //depot/misc/win-sourcedist/codemax/InsertChangeThread.cpp $
 * $Revision: #1 $
 * $Change: 2944 $
 * $DateTime: 2004/07/05 13:11:12 $
 * $Author: chrisc $
 * $Log$
 *****************************************************************************/

#include <vcl.h>
#pragma hdrstop

#include "EditForm.h"
#include "InsertChangeThread.h"
#pragma package(smart_init)

extern TParentForm      *ParentForm ;

void BuildDirList (TMenuItem *Menu, AnsiString Path) ;

__fastcall InsertChangeThread::InsertChangeThread (AnsiString Directory) : TThread (false)
{
  MonitorDir = Directory ;
}

//---------------------------------------------------------------------------
void DeleteInsertItems (TMenuItem *Menu)
{
  TMenuItem             *m ;

  for (int i = Menu->Count - 1 ; i >= 0 ; i--)
  {
    m = Menu->Items [i] ;
    Menu->Remove (m) ;
    if (m->Tag != 0)
      delete (AnsiString *) m->Tag ;
    DeleteInsertItems (m) ;
    delete m ;
  }
}

//---------------------------------------------------------------------------
void __fastcall InsertChangeThread::RebuildDirList (void)
{
  TMenuItem             *m ;

  for (int i = ParentForm->miInsertMenu->Count - 1 ; i > 2 ; i--)
  {
    m = ParentForm->miInsertMenu->Items [i] ;
    ParentForm->miInsertMenu->Remove (m) ;
    if (m->Tag != 0)
      delete (AnsiString *) m->Tag ;
    DeleteInsertItems (m) ;
    delete m ;
  }
  BuildDirList (ParentForm->miInsertMenu, MonitorDir) ;
}

//---------------------------------------------------------------------------
void __fastcall InsertChangeThread::Execute (void)
{
  bool                  finished = false ;
  HANDLE                handle ;

  // The Windows API documentation -claims- that if this function fails it
  // will return INVALID_HANDLE_VALUE. In actual fact, on rare instances,
  // it will return NULL, thus causing all sorts of problems later in this
  // code (because we didn't test for it - as per the documentation and even
  // Microsoft's own sample code).
  
  // We handle this situation now by re-acquiring it below rather than exiting.
  handle = FindFirstChangeNotification (MonitorDir.c_str (),
                                        true,
                                        FILE_NOTIFY_CHANGE_FILE_NAME |
                                        FILE_NOTIFY_CHANGE_DIR_NAME) ;
  while (!finished)
  {
    if (handle == INVALID_HANDLE_VALUE || handle == NULL)
    {
      Sleep (5000) ;
      handle = FindFirstChangeNotification (MonitorDir.c_str (),
                                            true,
                                            FILE_NOTIFY_CHANGE_FILE_NAME |
                                            FILE_NOTIFY_CHANGE_DIR_NAME) ;
      if (handle == INVALID_HANDLE_VALUE || handle == NULL)
        Sleep (60000) ;
    }
    if (WaitForSingleObject (handle, INFINITE) != WAIT_OBJECT_0 || FindNextChangeNotification (handle) == 0)
    {
      FindCloseChangeNotification (handle) ;
      handle = INVALID_HANDLE_VALUE ;
      Sleep (10000) ;
      continue ;
    }
    Synchronize ((TThreadMethod) &RebuildDirList) ;
    Sleep (1000) ;
  }
  FindCloseChangeNotification (handle) ;
}

//---------------------------------------------------------------------------


